为什么你写的ContentObserver不能及时收到回调?

您所在的位置:网站首页 content resolver的call 为什么你写的ContentObserver不能及时收到回调?

为什么你写的ContentObserver不能及时收到回调?

2023-10-26 17:55| 来源: 网络整理| 查看: 265

Android 在ContentObserver是有延迟机制的。先来了解下ContentObserver developer.android.google.cn/reference/a…

对于Android 相关问题,我都是习惯先去看看官方文档,毕竟官方文档给出来的结论和demo才是最权威的,以官方文档为基础,再结合网上的其他开源资料。关于如何使用ContentObserver不在本篇讨论范围,我们只关注ContentObserver在framework中做了哪些事情。

首先ContentObserver的操作对象是Uri,在ContentObserver正常工作的情况下,为什么明明监听的Uri状态发生了变化,却没有第一时间收到回调呢?

首先我们的ContentObserver观察的MediaProvider数据发生变化,此时MediaProvider本身会将这个变化通知给ContengObserver,然后ContengObserver会回调自己的onChange来将这个变化dispatch下去。

Android R

实际debug过的一个场景,应用层注册了ContentObserver来观察相册,然后手动删除照片,当应用受到onChange回调时,就弹出一个Dialog。事实发现,无论在什么场景下,删除照片之后都要等待10秒才会弹出Dialog,我们回顾一下这其中的framework流程

应用层删除数据 删除数据时需要调用ContentProvider自身的delete()方法 在执行delete过程中,会调用getContext().getContentResolver.notifyDelete() 调用notifyDelete时,会添加一个flag来表明此操作代表删除,并回调notifyChange() notifyChange()最终回调到ContentService,通过for循环依次通知注册此ContentObserver的对象并回调那里的onChange()。

以上就是ContentObserver在使用过程中,从数据变化到应用层收到onChange回调的全部framework流程。

在Android R版本有上一笔patch对后台进程的ContentObserver主动延迟10ms,以此来优化系统整体性功能。BugID:140249142 感兴趣可以去看下这笔修改

这笔修改涉及ContentServer中的一个关键方法dispatch() /frameworks/base/services/core/java/com/android/server/content/ContentService.java

556 public void dispatch() { 557 for (int i = 0; i < collected.size(); i++) { 558 final Key key = collected.keyAt(i); 559 final List value = collected.valueAt(i); 560 561 final Runnable task = () -> { 562 try { 563 key.observer.onChangeEtc(key.selfChange, 564 value.toArray(new Uri[value.size()]), key.flags, key.userId); 565 } catch (RemoteException ignored) { 566 } 567 }; 568 569 // Immediately dispatch notifications to foreground apps that 570 // are important to the user; all other background observers are 571 // delayed to avoid stampeding 572 final boolean noDelay = (key.flags & ContentResolver.NOTIFY_NO_DELAY) != 0; 573 final int procState = LocalServices.getService(ActivityManagerInternal.class) 574 .getUidProcessState(key.uid); // 这里是收到延迟回调的关键 575 if (procState


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3